﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Estimate.Common.DBFieldTypes;
using Estimate.Common.Repository;
using Estimate.Common.Entity;
using Estimate.Common.Estimate;
using System.IO;

namespace Estimate.Common.OldEstimate
{
    public class EstimateChecker
    {
        public static void CheckDayForeRecord(string oldConnectionString,ForeRepository repository,DateTime date,ForeSemiType semitype)
        {
            string filename = string.Format("{0}-{1}-{2}.txt", date.ToString("yyyy-MM-dd"),repository.TableName, semitype.ToString());
            Console.WriteLine("生成文件 "+filename+"\n");
            StreamWriter fs = File.CreateText(filename);
            Dictionary<string, List<string>> result = new Dictionary<string,List<string>>();
            foreach (ForeClockType clock in new ForeClockType[] { ForeClockType.H08, ForeClockType.H20 })
            {
                ForeSendpointType sendpoint;
                if (clock == ForeClockType.H08)
                {
                    sendpoint = ForeSendpointType.H06;
                }
                else
                {
                    sendpoint = ForeSendpointType.H16;
                }
                foreach (ForeSpanType span in new ForeSpanType[] { ForeSpanType.FD00_12, ForeSpanType.FD12_24, ForeSpanType.FD00_24, ForeSpanType.FD24_48, ForeSpanType.FD48_72, ForeSpanType.FD72_96, ForeSpanType.FD96_120 })
                {
                    foreach (ForeFactorType factor in new ForeFactorType[] { ForeFactorType.wth, ForeFactorType.maxt, ForeFactorType.mint })
                    {

                        Console.WriteLine(string.Format("处理记录, {0}, {1}, {2}, {3}, {4}, {5}", date.ToString("yyyy-MM-dd"), clock, span, sendpoint, factor, semitype));                        
                        EstimateChecker.CheckForeRecord(repository, oldConnectionString, date, clock, span, sendpoint, factor, semitype, result);                        
                    }
                }
            }

            //某些semi，旧数据计算的结果就是错的，在这里做排除。
            List<string> excludeKeys = new List<string>() { 
                "oldSemi: , newSemi: LackReal LackReal LackReal LackReal",  //缺实况数据
                "oldSemi: , newSemi: -102",  //缺实况数据
                "oldSemi: , newSemi: LackForecast LackForecast LackForecast LackForecast",
                "oldSemi: , newSemi: -101"
            };

            foreach (KeyValuePair<string, List<string>> pair in result)
            {
                if (excludeKeys.IndexOf(pair.Key) != -1)
                    continue;
                fs.WriteLine("---------------------------------------------------------------------------------------------------------------|");
                fs.WriteLine(pair.Key);
                fs.WriteLine("---------------------------------------------");
                fs.WriteLine("\n");
                foreach (string s in pair.Value)
                {
                    fs.WriteLine(s);
                }
                fs.WriteLine("\n");
            }
        }

        public static Dictionary<string, List<string>> CheckForeRecord(ForeRepository repository, string oldConnectionString, DateTime date, ForeClockType clock, ForeSpanType span, ForeSendpointType sendpoint, ForeFactorType type, ForeSemiType semitype, Dictionary<string, List<string>> infoHolder)
        {
            ForeEntity entity = repository.GetForeRecord(date, clock, span, sendpoint, type, semitype);
            if (entity == null)
            {
                Console.WriteLine("找不到相关记录");
                return new Dictionary<string, List<string>>();
            }
            string oldSemi, oldValue, oldReal;

            RealStationCompareType compareType =  Semier.GetCompareType(repository.TableName, entity.Semitype);
            Dictionary<string, string> foreStation4Real = GetForeRealStationDict(repository.ConnectionString, compareType);

            OldForeTableRepository.GetValueAndSemi(oldConnectionString, repository.TableName, date, clock, sendpoint, span, type, out oldValue, out oldSemi);
            oldReal = OldForeTableRepository.GetRealValue(oldConnectionString, date, type, span, clock);

            Dictionary<string, string[]> valueDict = new Dictionary<string, string[]>();
            //插入旧value
            foreach (string value in oldValue.Split(new char[] { '|' }))
            {
                if (value.Length == 0)
                    continue;
                string[] items = value.Split(new char[] { ';' });
                if (!valueDict.ContainsKey(items[0]))
                {
                    valueDict[items[0]] = new string[2] { items[1], "" };
                }
                else
                {
                    valueDict[items[0]][0] = items[1];
                }
            }
            //插入新value
            foreach (string value in entity.Value.Split(new char[] { '|' }))
            {
                if (value.Length == 0)
                    continue;
                string[] items = value.Split(new char[] { ';' });
                if (!valueDict.ContainsKey(items[0]))
                {
                    valueDict[items[0]] = new string[2] { "", items[1] };
                }
                else
                {
                    valueDict[items[0]][1] = items[1];
                }
            }
            
            Dictionary<string, string[]> semiDict = new Dictionary<string, string[]>();
            //插入旧semi
            foreach (string semi in oldSemi.Split(new char[] { '|' }))
            {
                if (semi.Length == 0)
                    continue;
                string[] items = semi.Split(new char[] { ';' });
                string station = semi.Substring(0, semi.IndexOf(';'));
                string s = semi.Substring(semi.IndexOf(';')+1);
                if (!semiDict.ContainsKey(station))
                {
                    semiDict[station] = new string[2] { s, "" };
                }
                else
                {
                    semiDict[station][0] = s;
                }
            }
            //插入新semi
            foreach (string semi in entity.Semi.Split(new char[] { '|' }))
            {
                if (semi.Length == 0)
                    continue;
                string station = semi.Substring(0, semi.IndexOf(';'));
                string s = semi.Substring(semi.IndexOf(';') + 1);
                if (!semiDict.ContainsKey(station))
                {
                    semiDict[station] = new string[2] { "",s };
                }
                else
                {
                    semiDict[station][1] = s;
                }
            }

            //存入实况数据
            Dictionary<string, string[]> realDict = new Dictionary<string, string[]>();
            //插入旧real
            foreach (string real in oldReal.Split(new char[] { '|' }))
            {
                if (real.Length == 0)
                    continue;
                string[] items = real.Split(new char[] { ';' });
                if (!realDict.ContainsKey(items[0]))
                {
                    realDict[items[0]] = new string[2] { items[1], "" };
                }
                else
                {
                    realDict[items[0]][0] = items[1];
                }
            }
            //插入新real
            string newReal = GetRealValue(repository.ConnectionString, date, type, span, clock,semitype);
            foreach (string real in newReal.Split(new char[] { '|' }))
            {
                if (real.Length == 0)
                    continue;
                string[] items = real.Split(new char[] { ';' });
                if (!realDict.ContainsKey(items[0]))
                {
                    realDict[items[0]] = new string[2] { "", items[1] };
                }
                else
                {
                    realDict[items[0]][1] = items[1];
                }
            }

            Dictionary<string, List<string>> result;
            if (infoHolder != null)
                result = infoHolder;
            else
                result = new Dictionary<string, List<string>>();


            List<string> excludeStation = new List<string>();
            if (repository.TableName == "St_SiteFore")
            {
                excludeStation.Add("58265");
                excludeStation.Add("58358");
                excludeStation.Add("58333");
            }

            //对比semi
            foreach (KeyValuePair<string, string[]> pair in semiDict)
            {
                if (!pair.Value[0].Equals(pair.Value[1]))
                {
                    if (excludeStation.IndexOf(pair.Key) != -1)
                        continue;
                    if( type == ForeFactorType.wth)
                    {
                        string oldSemiString = "";
                        if (pair.Value[0] != "")
                        {
                            WaterForecast oldForecast = new WaterForecast();
                            oldForecast.SetSemiResult(string.Format("{0};{1}", pair.Key, pair.Value[0]), semitype);
                            oldSemiString = oldForecast.ToString();
                        }

                        string newSemiString = "";
                        if(pair.Value[1] != "")
                        {
                            WaterForecast newForecast = new WaterForecast();
                            newForecast.SetSemiResult(string.Format("{0};{1}",pair.Key,pair.Value[1]), semitype);
                            newSemiString = newForecast.ToString();
                        }
                        


                        string key = string.Format("oldSemi: {0}, newSemi: {1}", oldSemiString, newSemiString);
                        if (!result.ContainsKey(key))
                        {
                            result[key] = new List<string>();
                        }

                        List<string> record = new List<string>();
                        if (!foreStation4Real.ContainsKey(pair.Key))
                            continue;
                        string realStation = foreStation4Real[pair.Key];
                        result[key].Add(string.Format("record, {0}, {1}, {2}, {3}, {4}, {5}\n", date.ToString("yyyy-MM-dd"), clock, span, sendpoint, type, semitype));
                        result[key].Add(string.Format("station: {0}, real station: {1}\n", pair.Key, realStation));
                        if (realDict.ContainsKey(realStation) && valueDict.ContainsKey(realStation) )
                        {
                            result[key].Add(string.Format("old  real:{0}, value:{1}\n", realDict[realStation][1], valueDict[pair.Key][1]));
                            result[key].Add(string.Format("new  real:{0}, value:{1}\n", realDict[realStation][1], valueDict[pair.Key][1]));
                        }
                        else if (!realDict.ContainsKey(realStation))
                        {
                            result[key].Add("实况数据中缺失站点\n");
                            result[key].Add(string.Format("old value:{0},new value:{1}\n", valueDict[pair.Key][0], valueDict[pair.Key][1]));
                        }
                        else
                        {
                            result[key].Add("预报数据中缺失站点\n");
                            result[key].Add(string.Format("old real:{0},new real:{1}\n", realDict[pair.Key][0], realDict[pair.Key][1]));
                        }
                        result[key].Add("\n");
                    }
                    else
                    {
                        
                        List<string> record = new List<string>();
                        if (!foreStation4Real.ContainsKey(pair.Key))
                            continue;
                        string realStation = foreStation4Real[pair.Key];

                        string key = string.Format("oldSemi: {0}, newSemi: {1}", pair.Value[0], pair.Value[1]);
                        

                        record.Add(string.Format("record, {0}, {1}, {2}, {3}, {4}, {5}\n", date.ToString("yyyy-MM-dd"), clock, span, sendpoint, type, semitype));
                        record.Add(string.Format("station: {0}, real station: {1}\n", pair.Key, realStation));
                        if (realDict.ContainsKey(realStation) && valueDict.ContainsKey(realStation))
                        {
                            if (realDict[realStation][1] == "999.9")
                                continue;
                            record.Add(string.Format("old  real:{0}, value:{1}\n", realDict[realStation][0], valueDict[pair.Key][0]));
                            record.Add(string.Format("new  real:{0}, value:{1}\n", realDict[realStation][1], valueDict[pair.Key][1]));
                        }
                        else if (!realDict.ContainsKey(realStation))
                        {
                            record.Add("实况数据中缺失站点\n");
                            record.Add(string.Format("old value:{0},new value:{1}\n", valueDict[pair.Key][0], valueDict[pair.Key][1]));
                        }
                        else
                        {
                            record.Add("预报数据中缺失站点\n");
                            record.Add(string.Format("old real:{0},new real:{1}\n", realDict[pair.Key][0], realDict[pair.Key][1]));
                        }
                        record.Add("\n");

                        if (!result.ContainsKey(key))
                        {
                            result[key] = new List<string>();
                        }
                        result[key].AddRange(record);
                    }
                }

            }


            return result;
        }



        public static Dictionary<string, string> GetForeRealStationDict(string connectionString, RealStationCompareType compareType)
        {
            RealStationCompareRepository repository = new RealStationCompareRepository(connectionString);
            ForeRealStationCompareEntity[] entitys = repository.GetAllRecord(compareType);
            
            Dictionary<string, string> foreStation4Real = new Dictionary<string, string>();
            foreach (ForeRealStationCompareEntity entity in entitys)
            {
                foreStation4Real[entity.ForeStation] = entity.RealStation;
            }

            return foreStation4Real;
        }

        public static string GetRealValue(string connectionString, DateTime date, ForeFactorType factor, ForeSpanType span, ForeClockType clock,ForeSemiType semitype)
        {
            ForeRealLinker linker = new ForeRealLinker();

            if (factor == ForeFactorType.wth)
            {
                RainRealRepository rainRepository;
                RainForeRealCompare comparer = linker.GetForeRelatedRainCondition(date, span, clock);
                if (semitype == ForeSemiType.Auto)
                {
                    rainRepository = RainRealRepositoryFactory.AutoStationRainRealRepository(connectionString);
                }
                else
                {
                    rainRepository = RainRealRepositoryFactory.ManualRainRealRepository(connectionString);
                }

                return rainRepository.GetValue(comparer.RealDate, comparer.RainType);
                
            }
            else if (factor == ForeFactorType.maxt || factor == ForeFactorType.mint)
            {
                TempRealRepository tempRepository;
                if (semitype == ForeSemiType.Auto)
                {
                    tempRepository = TempRealRepositoryFactory.AutoStationTempRealRepository(connectionString);
                }
                else
                {
                    tempRepository = TempRealRepositoryFactory.ManualTempRealRepository(connectionString);
                }

                TempForeRealCompare tempComparer = linker.GetForeRelatedTempCondition(date, span, clock, factor);

                return tempRepository.GetValue(tempComparer.RealDate, tempComparer.TempType);
            }
            else
                return "";
        }
    }
}
